package com.cd.music.service.impl;

import com.cd.music.dao.AuthCodeRecordDao;
import com.cd.music.dao.RoleDao;
import com.cd.music.dao.UserDao;
import com.cd.music.dao.UserLoginDao;
import com.cd.music.dao.UserLoginRecordDao;
import com.cd.music.dao.UserRoleDao;
import com.cd.music.dto.ResultBean;
import com.cd.music.dto.UserDto;
import com.cd.music.model.AuthCodeRecord;
import com.cd.music.model.Role;
import com.cd.music.model.UserLogin;
import com.cd.music.model.UserLoginRecord;
import com.cd.music.model.UserRole;
import com.cd.music.service.UserService;
import com.cd.music.utils.CookieUtil;
import com.cd.music.utils.IdUtil;
import com.cd.music.utils.StringUtil;
import com.cd.music.utils.TokenUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * @author yxl 余秀良
 * @version 1.0
 * @description: 用途
 * @date 2018年02月08日  下午2:38
 * @address: 四川成都
 */
@Transactional(readOnly = true, rollbackFor = Exception.class)
@Service(value = "userService")
public class UserServiceImpl implements UserService {
    @Resource
    private UserDao userDao;
    @Resource
    private UserLoginRecordDao userLoginRecordDao;
    @Resource
    private UserLoginDao userLoginDao;
    @Resource
    private AuthCodeRecordDao authCodeRecordDao;
    @Resource
    private RoleDao roleDao;
    @Resource
    private UserRoleDao userRoleDao;

    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    @Override
    public ResultBean login(UserDto dto) {
        ResultBean.Builder builder = ResultBean.builder();
        if (dto != null) {
            if (!StringUtil.isEmpty(dto.getPhone()) && !StringUtil.isEmpty(dto.getPassword()) && !StringUtil.isEmpty(dto.getVerificationCode())) {
                UserDto.Builder userDtoBuilder = UserDto.builder();
                //设置登录信息
                userDtoBuilder.phone(dto.getPhone()).password(dto.getPassword()).verificationCode(dto.getVerificationCode()).sign(-1);
                //调用登录方法
                UserDto login = userDao.login(userDtoBuilder.build());
                //确认验证码是否正确
                String msg = "登录失败，用户名或密码不正确";
                if (login != null) {
                    login.setVerificationCode(dto.getVerificationCode());
                }
                if (checkAuthCode(login, builder, msg)) {
                    loginSetResultInfo(builder, login, msg);
                }
            } else {
                builder.code(500).message("请检查参数是否完整").success(false);
            }
        } else {
            builder.code(500).message("参数不能为空").success(false);
        }
        return builder.build();
    }

    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    @Override
    public ResultBean adminLogin(UserDto dto) {
        ResultBean.Builder builder = ResultBean.builder();
        if (dto != null) {
            if (!StringUtil.isEmpty(dto.getPhone()) && !StringUtil.isEmpty(dto.getPassword())) {
                UserDto.Builder userDtoBuilder = UserDto.builder();
                //设置登录信息　管理员登录需要设置角色权重参数　管理员为0
                userDtoBuilder.phone(dto.getPhone()).password(dto.getPassword()).sign(0);
                //调用登录方法
                UserDto userDto = userDao.login(userDtoBuilder.build());
                if (userDto != null) {
                    int sign = userDto.getSign();
                    if (sign != 0 && sign != 1) {
                        return builder.code(200).message("没有权限").success(false).build();
                    }
                }
                //确认验证码是否正确
                String msg = "登录失败，请确认是否是管理员,并检查用户名和密码是否正确";
                loginSetResultInfo(builder, userDto, msg);
            } else {
                builder.code(500).message("请检查参数是否完整").success(false);
            }
        } else {
            builder.code(500).message("参数不能为空").success(false);
        }
        return builder.build();
    }

    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, timeout = 36000, rollbackFor = Exception.class)
    @Override
    public ResultBean register(UserDto dto) {
        ResultBean.Builder builder = ResultBean.builder();
        if (dto != null) {
            if (!StringUtil.isEmpty(dto.getPhone()) && !StringUtil.isEmpty(dto.getPassword()) && !StringUtil.isEmpty(dto.getConfirmPassword()) && !StringUtil.isEmpty(dto.getVerificationCode())) {
                if (dto.getPassword().equals(dto.getConfirmPassword())) {
                    //查询帐号是否存在,做唯一性验证
                    UserDto userDto = userDao.queryUser(dto.getPhone());
                    if (userDto != null) {
                        builder.code(200).message("该用户已存在").success(false);
                    } else {
                        //做验证码的校验，检查验证码是否正确
                        if (checkAuthCode(dto, builder, "")) {
                            //添加到用户表
                            boolean addUserOk = registerAddUser(dto);
                            if (addUserOk) {
                                //添加到用户登录表
                                boolean addUserLogin = registerAddUserLogin(dto);
                                //添加用户角色表
                                if (addUserLogin) {
                                    boolean addUserRole = registerAddUserRole(dto);
                                    if (addUserRole) {
                                        builder.code(200).message("注册成功").success(true);
                                    } else {
                                        builder.code(500).message("注册失败").success(false);
                                    }
                                } else {
                                    builder.code(500).message("注册失败").success(false);
                                }
                            } else {
                                builder.code(500).message("注册失败").success(false);
                            }
                        }
                    }
                } else {
                    builder.code(200).message("密码和确认密码不一致").success(false);
                }
            } else {
                builder.code(400).message("请检查信息是否完整").success(false);
            }
        } else {
            builder.code(400).message("参数不能为空").success(false);
        }
        return builder.build();
    }

    @Override
    public ResultBean selectUser(UserDto dto) {
        ResultBean.Builder builder = ResultBean.builder();
        if (dto != null) {
            UserDto userDto = userDao.queryUser(dto.getPhone());
            if (userDto != null) {
                builder.message("成功").success(true).data(userDto);
            } else {
                builder.message("该帐号不存在").success(false);
            }
        } else {
            builder.code(400).message("参数不能为空").success(false);
        }
        return builder.build();
    }

    /**
     * 查询用户
     *
     * @param dto 用户信息参数
     * @return 用户列表
     * @author yxl 余秀良
     * @version 1.0
     * @description: 查询用户
     * @date 2018年02月08日 下午2:41
     * @address: 四川成都
     */
    @Override
    public ResultBean selectUserList(UserDto dto) {
        ResultBean.Builder builder = ResultBean.builder();
        if (dto != null) {
            List<Map> userList = userDao.userList(dto);
            builder.data(userList).success(true).message("成功");
        } else {
            builder.code(400).message("参数不能为空").success(false);
        }
        return builder.build();
    }

    /**
     * @param dto 参数：新密码
     * @return 状态
     * @author yxl 余秀良
     * @version 1.0
     * @description: 修改密码
     * @date 2018年03月06日 下午4:35
     * @address: 四川成都
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public ResultBean userUpdatePwd(UserDto dto) {
        ResultBean.Builder builder = ResultBean.builder();
        if (dto != null) {
            //用户手机号码
            String phone = dto.getPhone();
            //密码
            String password = dto.getPassword();
            //确认密码
            String confirmPassword = dto.getConfirmPassword();
            //验证码
            String verificationCode = dto.getVerificationCode();
            if (!StringUtil.isEmpty(phone) && !StringUtil.isEmpty(verificationCode) && !StringUtil.isEmpty(password) && !StringUtil.isEmpty(confirmPassword)) {
                if (password.equals(confirmPassword)) {
                    //查询帐号是否存在,做唯一性验证
                    UserDto userDto = userDao.queryUser(phone);
                    if (userDto != null) {
                        String userId = userDto.getId();
                        UserLogin userLogin = new UserLogin();
                        userLogin.setUserId(userId);
                        userLogin.setPassword(password);
                        boolean isOk = userLoginDao.updatePwd(userLogin) > 0;
                        builder.success(isOk).message(isOk ? "成功" : "失败");
                    } else {
                        builder.code(200).message("该用户不存在").success(false);
                    }
                } else {
                    builder.code(200).message("密码和确认密码不一致").success(false);
                }
            }
        }
        return builder.build();
    }

    /**
     * 修改密码
     *
     * @param dto 参数：新密码,确认密码
     * @return 状态
     * @author yxl 余秀良
     * @version 1.0
     * @description: 修改密码
     * @date 2018年03月06日 下午4:35
     * @address: 四川成都
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public ResultBean adminUpdatePwd(UserDto dto) {
        ResultBean.Builder builder = ResultBean.builder();
        if (dto != null) {
            ResultBean resultBean = CookieUtil.get("token");
            String token = resultBean.getData();
            if (StringUtil.isEmpty(token)) {
                return builder.code(403).message("请登录后再试").success(false).build();
            }
            Map map = TokenUtil.getParameter(token, Map.class);
            String userId = map.get("userId") + "";
            String password = dto.getPassword();
            String confirmPassword = dto.getConfirmPassword();
            if (!StringUtil.isEmpty(userId) && !StringUtil.isEmpty(password) && !StringUtil.isEmpty(confirmPassword)) {
                if (password.equals(confirmPassword)) {
                    UserLogin userLogin = new UserLogin();
                    userLogin.setUserId(userId);
                    userLogin.setPassword(password);
                    boolean isOk = userLoginDao.updatePwd(userLogin) > 0;
                    builder.success(isOk).code(200).message(isOk ? "成功" : "失败");
                } else {
                    builder.code(400).message("密码和确认密码不一致").success(false);
                }
            } else {
                builder.code(400).message("请检查信息是否完整").success(false);
            }
        } else {
            builder.code(400).message("参数不能为空").success(false);
        }
        return builder.build();
    }

    /**
     * 登录记录
     *
     * @param dto 参数
     * @return 　登录记录
     * @author yxl 余秀良
     * @version 1.0
     * @description: 登录记录
     * @date 2018年03月08日 下午3:34
     * @address: 四川成都
     */
    @Override
    public ResultBean loginRecord(UserDto dto) {
        ResultBean.Builder builder = ResultBean.builder();
        if (dto != null) {
            if (dto.getPageIndex() != null && dto.getPageSize() != null) {
                Integer index = dto.getPageIndex();
                Integer pageSize = dto.getPageSize();
                Integer pageIndex = (index <= 0) ? 0 : ((index - 1) * pageSize);
                dto.setPageIndex(pageIndex);
                List<Map> select = userLoginRecordDao.loginRecord(dto);
                Long total = userLoginRecordDao.loginRecordTotal();
                Map<String, Object> map = new LinkedHashMap<>();
                map.put("list", select);
                map.put("pageIndex", index);
                map.put("total", total);
                builder.data(map).message(select.size() > 0 ? "成功" : "没有数据").success(true);
            } else {
                builder.code(400).message("请检查参数").success(false);
            }
        } else {
            builder.code(400).message("参数不能为空").success(false);
        }
        return builder.build();
    }

    /**
     * 禁用用户帐号
     *
     * @param dto 用户id
     * @return 返回操作说明
     * @author yxl 余秀良
     * @version 1.0
     * @description: 禁用用户帐号
     * @date 2018年03月12日 上午10:25
     * @address: 四川成都
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public ResultBean disableUserAccount(UserDto dto) {
        ResultBean.Builder builder = ResultBean.builder();
        if (dto != null) {
            String userId = dto.getUserId();
            if (!StringUtil.isEmpty(userId)) {
                UserLogin userLogin = new UserLogin();
                userLogin.setUserId(userId);
                userLogin.setAccountStatus(-1);
                boolean isOk = userLoginDao.updateByPrimaryKeySelective(userLogin) > 0;
                builder.message(isOk ? "成功" : "失败").code(200).success(isOk);
            } else {
                builder.success(false).code(400).message("缺少必要参数");
            }
        } else {
            builder.message("参数不能为空").code(400).success(false);
        }
        return builder.build();
    }

    /**
     * 注册的时候添加用户表
     *
     * @return true/false
     */
    private boolean registerAddUser(UserDto dto) {
        dto.setId(IdUtil.getUUID());
        return userDao.addUser(dto) > 0;
    }

    /**
     * 注册的时候添加用户登录表
     *
     * @return true/false
     */
    private boolean registerAddUserLogin(UserDto dto) {
        UserLogin userLogin = new UserLogin();
        userLogin.setUserId(dto.getId());
        userLogin.setAccountStatus(0);
        userLogin.setPassword(dto.getPassword());
        userLogin.setId(IdUtil.getUUID());
        Map<String, Object> tokenMap = new LinkedHashMap<>(16);
        tokenMap.put("phone", dto.getPhone());
        tokenMap.put("userId", dto.getId());
        tokenMap.put("sign", dto.getSign());
        userLogin.setToken(TokenUtil.getToken(tokenMap, 7));
        return userLoginDao.insertSelective(userLogin) > 0;
    }

    /**
     * 注册的时候添加用户角色表
     *
     * @return true/false
     */
    private boolean registerAddUserRole(UserDto dto) {
        Role role = new Role();
        //设置为普通用户
        role.setSign(2);
        Role roleDaoResult = roleDao.selectRole(role);
        UserRole userRole = new UserRole();
        userRole.setId(IdUtil.getUUID());
        userRole.setUserId(dto.getId());
        userRole.setRoleId(roleDaoResult.getId());
        return userRoleDao.insert(userRole) > 0;
    }

    /**
     * 校验验证码是否正确
     *
     * @return 正确还是错误
     */
    private boolean checkAuthCode(UserDto dto, ResultBean.Builder builder, String msg) {
        if (dto != null) {
            AuthCodeRecord codeRecord = authCodeRecordDao.selectAuthCodeByPhone(dto.getPhone());
            if (codeRecord != null) {
                //验证码已经过期
                if (codeRecord.getIsExpire()) {
                    builder.code(200).success(false).message("验证码已过期").data(dto.getVerificationCode());
                    return false;
                }
                //验证码已经使用
                if (codeRecord.getIsUse()) {
                    builder.code(200).success(false).message("验证码已使用").data(dto.getVerificationCode());
                    return false;
                }

                if (!codeRecord.getIsExpire() && !codeRecord.getIsUse()) {
                    String verificationCode = codeRecord.getVerificationCode();
                    boolean equals = dto.getVerificationCode().equals(verificationCode);
                    if (equals) {
                        AuthCodeRecord record = new AuthCodeRecord();
                        record.setPhone(dto.getPhone());
                        record.setIsUse(true);
                        authCodeRecordDao.updateAuthCodeStatus(record);
                    } else {
                        builder.code(200).success(false).message("验证码不正确").data(dto.getVerificationCode());
                    }
                    return equals;
                }
                return false;
            } else {
                builder.code(200).success(false).message("验证码不正确").data(dto.getVerificationCode());
                return false;
            }
        } else {
            builder.code(200).message(msg).success(false);
            return false;
        }
    }

    /**
     * 判断登录是否成功并设置返回信息
     * 成功后修改用户的令牌和添加登录记录
     *
     * @param builder Builder
     * @param dto     UserDto
     * @param msg     提示消息
     */
    private void loginSetResultInfo(ResultBean.Builder builder, UserDto dto, String msg) {
        if (dto != null) {
            //修改用户登录表的身份令牌和登录状态
            loginUpdateUserLogin(dto);
            //如果登录成功则向登录记录表插入数据
            loginAddLoginRecord(dto);
            //设置返回给前端的信息
            Map<String, Object> map = new LinkedHashMap<>(16);
            map.put("token", dto.getToken());
            map.put("roleName", dto.getRoleName());
            map.put("userName", dto.getPhone());
            map.put("sign", dto.getSign());
            CookieUtil.set("token", dto.getToken());
            builder.message("登录成功").success(true).data(map);
        } else {
            builder.message(msg).success(false);
        }
    }

    /**
     * @author yxl 余秀良
     * @version 1.0
     * @description: 登录成功的时候向数据库添加登录记录信息
     * @date 2018年03月01日 上午10:37
     * @address: 四川成都
     */
    private void loginUpdateUserLogin(UserDto dto) {
        UserLogin record = new UserLogin();
        record.setLoginStatus(1);
        record.setUserId(dto.getId());
        if (StringUtil.isEmpty(dto.getToken()) || TokenUtil.isExpiration(dto.getToken())) {
            Map<String, Object> tokenMap = new LinkedHashMap<>(16);
            tokenMap.put("phone", dto.getPhone());
            tokenMap.put("userId", dto.getId());
            tokenMap.put("sign", dto.getSign());
            String token = TokenUtil.getToken(tokenMap, 7);
            record.setToken(token);
            dto.setToken(token);
        }
        userLoginDao.updateByPrimaryKeySelective(record);
    }

    /**
     * @author yxl 余秀良
     * @version 1.0
     * @description: 向数据库添加登录记录信息
     * @date 2018年03月01日 上午10:37
     * @address: 四川成都
     */
    private void loginAddLoginRecord(UserDto dto) {
        UserLoginRecord record = new UserLoginRecord();
        record.setId(IdUtil.getUUID());
        record.setUserId(dto.getId());
        record.setPhone(dto.getPhone());
        record.setIdentityType(dto.getName());
        userLoginRecordDao.insertLoginRecord(record);
    }
}
